﻿using TaleWorlds.Core;

namespace MarriageFertility.Helpers;

public static class EquipmentComparer
{
    public static bool BetterWeapon(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        WeaponClass heroWeaponClass = heroEquipment.Item.WeaponComponent.PrimaryWeapon.WeaponClass;
        switch (heroWeaponClass)
        {
            case WeaponClass.Dagger:
                return BetterOneHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.OneHandedSword:
                return BetterOneHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.TwoHandedSword:
                return BetterTwoHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.OneHandedAxe:
                return BetterOneHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.TwoHandedAxe:
                return BetterTwoHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.Mace:
                return BetterMace(heroEquipment, newEquipment);
            case WeaponClass.Pick:
                return BetterTwoHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.TwoHandedMace:
                return BetterTwoHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.OneHandedPolearm:
                return BetterOneHandPolearm(heroEquipment, newEquipment);
            case WeaponClass.TwoHandedPolearm:
                return BetterTwoHandedWeapon(heroEquipment, newEquipment);
            case WeaponClass.LowGripPolearm:
                return BetterOneHandPolearm(heroEquipment, newEquipment);
            case WeaponClass.Arrow:
                return BetterAmmo(heroEquipment, newEquipment);
            case WeaponClass.Bolt:
                return BetterAmmo(heroEquipment, newEquipment);
            case WeaponClass.Cartridge:
                return BetterAmmo(heroEquipment, newEquipment);
            case WeaponClass.Bow:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Crossbow:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Stone:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Boulder:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.ThrowingAxe:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.ThrowingKnife:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Javelin:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Pistol:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.Musket:
                return BetterRangeWeapon(heroEquipment, newEquipment);
            case WeaponClass.SmallShield:
                return newEquipment.Item.Effectiveness > heroEquipment.Item.Effectiveness;
            case WeaponClass.LargeShield:
                return newEquipment.Item.Effectiveness > heroEquipment.Item.Effectiveness;
            default:
                return false;
        }
    }
    
    private static bool BetterOneHandedWeapon(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int swingDamage1 = heroEquipment.GetModifiedSwingDamageForUsage(0);
        int thrustDamage1 = heroEquipment.GetModifiedThrustDamageForUsage(0);
        int swingSpeed1 = heroEquipment.GetModifiedSwingSpeedForUsage(0);
        int thrustSpeed1 = heroEquipment.GetModifiedThrustSpeedForUsage(0);

        int swingDamage2 = newEquipment.GetModifiedSwingDamageForUsage(0);
        int thrustDamage2 = newEquipment.GetModifiedThrustDamageForUsage(0);
        int swingSpeed2 = newEquipment.GetModifiedSwingSpeedForUsage(0);
        int thrustSpeed2 = newEquipment.GetModifiedThrustSpeedForUsage(0);

        double score1 = 0.4 * (swingDamage1 + thrustDamage1) + 0.3 * (swingSpeed1 + thrustSpeed1);
        double score2 = 0.4 * (swingDamage2 + thrustDamage2) + 0.3 * (swingSpeed2 + thrustSpeed2);
        return score2 > score1;
    }

    private static bool BetterTwoHandedWeapon(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int swingDamage1 = heroEquipment.GetModifiedSwingDamageForUsage(0);
        int thrustDamage1 = heroEquipment.GetModifiedThrustDamageForUsage(0);
        int swingSpeed1 = heroEquipment.GetModifiedSwingSpeedForUsage(0);
        int thrustSpeed1 = heroEquipment.GetModifiedThrustSpeedForUsage(0);

        int swingDamage2 = newEquipment.GetModifiedSwingDamageForUsage(0);
        int thrustDamage2 = newEquipment.GetModifiedThrustDamageForUsage(0);
        int swingSpeed2 = newEquipment.GetModifiedSwingSpeedForUsage(0);
        int thrustSpeed2 = newEquipment.GetModifiedThrustSpeedForUsage(0);

        double score1 = 0.4 * (swingDamage1 + thrustDamage1) + 0.3 * (swingSpeed1 + thrustSpeed1);
        double score2 = 0.4 * (swingDamage2 + thrustDamage2) + 0.3 * (swingSpeed2 + thrustSpeed2);
        return score2 > score1;
    }

    private static bool BetterOneHandPolearm(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int thrustDamage1 = heroEquipment.GetModifiedThrustDamageForUsage(0);
        int thrustSpeed1 = heroEquipment.GetModifiedThrustSpeedForUsage(0);

        int thrustDamage2 = newEquipment.GetModifiedThrustDamageForUsage(0);
        int thrustSpeed2 = newEquipment.GetModifiedThrustSpeedForUsage(0);

        double score1 = 0.4 * thrustDamage1 + 0.3 * thrustSpeed1;
        double score2 = 0.4 * thrustDamage2 + 0.3 * thrustSpeed2;
        return score2 > score1;
    }

    private static bool BetterMace(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int swingDamage1 = heroEquipment.GetModifiedSwingDamageForUsage(0);
        int swingSpeed1 = heroEquipment.GetModifiedSwingSpeedForUsage(0);

        int swingDamage2 = newEquipment.GetModifiedSwingDamageForUsage(0);
        int swingSpeed2 = newEquipment.GetModifiedSwingSpeedForUsage(0);

        double score1 = swingDamage1 + swingSpeed1;
        double score2 = swingDamage2 + swingSpeed2;
        return score2 > score1;
    }

    private static bool BetterAmmo(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int damage1 = heroEquipment.GetModifiedMissileDamageForUsage(0);
        int damage2 = newEquipment.GetModifiedMissileDamageForUsage(0);
        return damage2 > damage1;
    }

    private static bool BetterRangeWeapon(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int damage1 = heroEquipment.GetModifiedMissileDamageForUsage(0);
        int damage2 = newEquipment.GetModifiedMissileDamageForUsage(0);

        int speed1 = heroEquipment.GetModifiedMissileSpeedForUsage(0);
        int speed2 = newEquipment.GetModifiedMissileSpeedForUsage(0);

        double score1 = 0.5 * damage1 + 0.3 * speed1;
        double score2 = 0.5 * damage2 + 0.3 * speed2;

        return score2 > score1;
    }

    public static bool BetterArmor(Equipment heroFullEquipment, EquipmentElement heroEquipment, EquipmentElement newEquipment, EquipmentIndex armorIndex)
    {
        if (heroEquipment.Item == null || newEquipment.Item == null) return true;
        switch (armorIndex)
        {
            case EquipmentIndex.Head:
                return BetterHeadArmor(heroEquipment, newEquipment);
            case EquipmentIndex.Body:
                return BetterBodyArmor(heroEquipment, newEquipment);
            case EquipmentIndex.Cape:
                return BetterCapeArmor(heroEquipment, newEquipment);
            case EquipmentIndex.Leg:
                return BetterLegArmor(heroEquipment, newEquipment);
            case EquipmentIndex.Gloves:
                return BetterArmArmor(heroEquipment, newEquipment);
            case EquipmentIndex.HorseHarness:
                return BetterHorseArmor(heroFullEquipment, heroEquipment, newEquipment);
            default:
                return newEquipment.Item.Effectiveness > heroEquipment.Item.Effectiveness;
        }
    }

    private static bool BetterHeadArmor(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int armor1 = heroEquipment.GetModifiedHeadArmor();
        int armor2 = newEquipment.GetModifiedHeadArmor();
        return armor2 > armor1;
    }

    private static bool BetterCapeArmor(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int headArmor1 = heroEquipment.GetModifiedHeadArmor();
        int headArmor2 = newEquipment.GetModifiedHeadArmor();

        int bodyArmor1 = heroEquipment.GetModifiedBodyArmor();
        int bodyArmor2 = newEquipment.GetModifiedBodyArmor();

        int armArmor1 = heroEquipment.GetModifiedArmArmor();
        int armArmor2 = newEquipment.GetModifiedArmArmor();

        int legArmor1 = heroEquipment.GetModifiedLegArmor();
        int legArmor2 = newEquipment.GetModifiedLegArmor();

        double score1 = headArmor1 + bodyArmor1 + armArmor1 + legArmor1;
        double score2 = headArmor2 + bodyArmor2 + armArmor2 + legArmor2;
        return score2 > score1;
    }

    private static bool BetterBodyArmor(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int headArmor1 = heroEquipment.GetModifiedHeadArmor();
        int headArmor2 = newEquipment.GetModifiedHeadArmor();
        int bodyArmor1 = heroEquipment.GetModifiedBodyArmor();
        int bodyArmor2 = newEquipment.GetModifiedBodyArmor();

        int legArmor1 = heroEquipment.GetModifiedLegArmor();
        int legArmor2 = newEquipment.GetModifiedLegArmor();

        int armArmor1 = heroEquipment.GetModifiedArmArmor();
        int armArmor2 = newEquipment.GetModifiedArmArmor();

        double score1 = headArmor1 + bodyArmor1 + legArmor1 + armArmor1;
        double score2 = headArmor2 + bodyArmor2 + legArmor2 + armArmor2;
        return score2 > score1;
    }

    private static bool BetterArmArmor(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int armArmor1 = heroEquipment.GetModifiedArmArmor();
        int armArmor2 = newEquipment.GetModifiedArmArmor();
        return armArmor2 > armArmor1;
    }

    private static bool BetterLegArmor(EquipmentElement heroEquipment, EquipmentElement newEquipment)
    {
        int legArmor1 = heroEquipment.GetModifiedLegArmor();
        int legArmor2 = newEquipment.GetModifiedLegArmor();
        return legArmor2 > legArmor1;
    }

    public static bool BetterHorseArmor(Equipment heroFullEquipment, EquipmentElement heroHorseArmor, EquipmentElement newHorseArmor)
    {
        // Check if the hero has a mount in the EquipmentIndex.Mount slot
        if (heroFullEquipment[EquipmentIndex.Horse].Item == null)
        {
            return false; // No mount, so no need to buy horse armor
        }

        // If no current horse armor is equipped, the new armor is better
        if (heroHorseArmor.Item == null)
        {
            return true;
        }

        // Compare mount armor values
        int mountArmor1 = heroHorseArmor.GetModifiedMountBodyArmor();
        int mountArmor2 = newHorseArmor.GetModifiedMountBodyArmor();
        return mountArmor2 > mountArmor1;
    }
}